// Copyright (c) 2008-2010, Arne Claus
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
// following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this list of conditions and the following 
//   disclaimer.
// - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
//   disclaimer in the documentation and/or other materials provided with the distribution.
// - Neither the name Arne Claus nor the names of any contributors may be used to endorse or promote products
//   derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef __INCLUDED_CBL_XML_SERIALIZER_H__
#define __INCLUDED_CBL_XML_SERIALIZER_H__

#include "CBL_Serialization.h"
#include "CBL_FileSystem.h"

CB_NAMESPACE_START

// --------------------------------------------------------------------------------------------------------------------
//	CXMLSerializer is a fast and very lightweight XML reader and writer.
//  It supports the absolute minimum necessary to ready basic XML-Files and tries to keep memory usage and
//  allocations / deallocations low,
// --------------------------------------------------------------------------------------------------------------------

class CXMLNode;

class CXMLSerializer : public ISerializer
{
public:
    
    static const uint32 FlagInlineBlockData = FirstCustomFlag << 0;
    
public:
    
    BASELIB_API CXMLSerializer(EOutputType _Type, const IFileSystem& _rFileSystem, const char* _pFileName);
    BASELIB_API CXMLSerializer(EOutputType _Type, const char* _pData=NULL);
    BASELIB_API virtual ~CXMLSerializer();
    
    BASELIB_API virtual Memory::CAutoBuffer<char> Flush();
    
    BASELIB_API virtual bool Serialize(bool& _rValue, const char* _pName, uint32 _Flags=0);
    
    BASELIB_API virtual bool Serialize(int8& _rValue, const char* _pName, uint32 _Flags=0);
    BASELIB_API virtual bool Serialize(int16& _rValue, const char* _pName, uint32 _Flags=0);
    BASELIB_API virtual bool Serialize(int32& _rValue, const char* _pName, uint32 _Flags=0);
    BASELIB_API virtual bool Serialize(int64& _rValue, const char* _pName, uint32 _Flags=0);
    
    BASELIB_API virtual bool Serialize(uint8& _rValue, const char* _pName, uint32 _Flags=0);
    BASELIB_API virtual bool Serialize(uint16& _rValue, const char* _pName, uint32 _Flags=0);
    BASELIB_API virtual bool Serialize(uint32& _rValue, const char* _pName, uint32 _Flags=0);
    BASELIB_API virtual bool Serialize(uint64& _rValue, const char* _pName, uint32 _Flags=0);
    
    BASELIB_API virtual bool Serialize(uint32& _rValue, const char** _pTranslationStringArray, uint32 _ArrayLength, const char* _pName, uint32 _Flags=0);
    
    BASELIB_API virtual bool Serialize(float& _rValue, const char* _pName, uint32 _Flags=0);
    BASELIB_API virtual bool Serialize(double& _rValue, const char* _pName, uint32 _Flags=0);
    
    BASELIB_API virtual bool Serialize(char* _pValue, size_t _BufferSize, const char* _pName, uint32 _Flags=0);
    BASELIB_API virtual bool Serialize(wchar_t* _pValue, size_t _BufferSize, const char* _pName, uint32 _Flags=0);
    
    BASELIB_API virtual bool Serialize(std::string& _rValue, const char* _pName, uint32 _Flags=0);
    BASELIB_API virtual bool Serialize(std::wstring& _rValue, const char* _pName, uint32 _Flags=0);
    
    BASELIB_API virtual bool Serialize(ISerializeable& _rObject, const char* _pName, uint32 _Flags=0);
    BASELIB_API virtual bool Serialize(ISerializeable** _ppObject, const char* _pName, uint32 _Flags=0);
    
    BASELIB_API virtual bool SerializeBlockStart(const char* _pName, uint32 _Flags=0);
    BASELIB_API virtual bool SerializeBlockEnd(const char* _pName, uint32 _Flags=0);
    
private:

    const std::string& ReadValueString(const char* _pName, uint32 _Flags);
	void AddValueString(const char* _pName, const char* _pValue, uint32 _Flags);

private:

	enum EParserMode
    {
    	ReadingHead = 0,
    	ReadingTag,
        ReadingMeta,
        ReadingNodeName,
        ReadingAttributeName,
        ReadingAttributeStart,
        ReadingAttribute,
    	ReadingComment,
        ReadingBlock,
    	ReadingCloseBlock,
    	ReachedEOB,
    	ReachedEOF,
        
        NumParserModes
    };

	EParserMode Progress(const char* _pNode);
	void Parse(CXMLNode* _pNode, const char* _pData, EParserMode _ReturnOnMode);
    
    void AddToParserBuffer(char _Char);
    
    void OnReadingTag();
    void OnReadingMeta();
    void OnReadingNodeName();
    void OnReadingAttributeName();
    void OnReadingAttributeStart();
    void OnReadingAttribute();
    void OnReadingComment();
    void OnReadingBlock(const char* _pData);
	void OnReadingCloseBlock();
    
private:

	std::string ToString();
	std::string NodeToString(CXMLNode* _pNode, uint32 _Depth=0);

private:
    
    EParserMode     m_ParserMode;
    uint32			m_ParserDataIdx;
    uint32			m_ParseBufferIdx;
    char			m_ParserBuffer[4096]; 		// can read up to 4 KB of Texts
    char			m_AttributeNameBuffer[255];
    
    CXMLNode*		m_pCurrentNode;
    CXMLNode*		m_pCurrentParent;
    
    CXMLNode*		m_pRoot;
    CFileHandlePtr	m_FileHandle;
};
    
CB_NAMESPACE_END
    
#endif